#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "led.h"
// #include "driver/timer.h"

// #include <stdlib.h>

// #include "driver/ledc.h"
// #include "my_pwm.h"
#include "my_adc.h"

// #define LEDC_MAX_DUTY   (8191)
// #define LEDC_FADE_TIME  (1000)
void app_main(void)
{
    esp_err_t ret;
    uint32_t ret_num = 0;
    uint8_t result[TIMES] = {0};
    memset(result, 0xcc, TIMES);//把数组result里面的times个值都初始化成0xcc=204;
    // continuous_adc_init(adc1_chan_mask, adc2_chan_mask, channel, sizeof(channel) / sizeof(adc_channel_t));//初始化配置
    my_adc_dma_init();
    adc_digi_start();//启动转换
    while (1)
    {
        ret = adc_digi_read_bytes(result, TIMES, &ret_num, ADC_MAX_DELAY);//读取转换数据，数据存在result里面，预期是256个，实际是ret_num个。转换超时时间限制是最大
        //判断adc_digi_read_bytes返回的参数，成功、驱动设备未安装（残阳速率大于任务处理速率）、超时
        if (ret == ESP_OK || ret == ESP_ERR_INVALID_STATE) 
        {
            if (ret == ESP_ERR_INVALID_STATE) 
            {
                /**
                 * 对于普通的只打印任务处理速率还是很快的
                 * 
                 * @note 1
                 * Issue:
                 * As an example, we simply print the result out, which is super slow. Therefore the conversion is too
                 * fast for the task to handle. In this condition, some conversion results lost.
                 *
                 * Reason:
                 * When this error occurs, you will usually see the task watchdog timeout issue also.
                 * Because the conversion is too fast, whereas the task calling `adc_digi_read_bytes` is slow.
                 * So `adc_digi_read_bytes` will hardly block. Therefore Idle Task hardly has chance to run. In this
                 * example, we add a `vTaskDelay(1)` below, to prevent the task watchdog timeout.
                 *
                 * Solution:
                 * Either decrease the conversion speed, or increase the frequency you call `adc_digi_read_bytes`
                 */
                printf("ERROR:请降低转换速度,或者增加调用adc_digi_read_bytes的频率\n" );
            }
            for (int i = 0; i < ret_num; i += ADC_RESULT_BYTE) 
            {
                adc_digi_output_data_t *p = (void*)&result[i]; //把result中的数据传到adc_digi_output_data_t中，（void*）就是可以把数据转换成任意类型的数据
    #if CONFIG_IDF_TARGET_ESP32
                ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 1, p->type1.channel, p->type1.data);//如果选择的是ESP32那么输出使用的哪个ADC的哪个通道以及那种类型的数据
    #else
                if (ADC_CONV_MODE == ADC_CONV_BOTH_UNIT || ADC_CONV_MODE == ADC_CONV_ALTER_UNIT) //判断ADC转换模式时ADC1、2,或者是轮流转换
                {
                    //判断数据是否有效
                    if (check_valid_data(p))
                    {
                        ESP_LOGI(TAG, "Unit: %d,_Channel: %d, Value: %x", p->type2.unit+1, p->type2.channel, p->type2.data);//输出有效数据
                    } else 
                    {
                        // abort();
                        ESP_LOGI(TAG, "Invalid data [%d_%d_%x]", p->type2.unit+1, p->type2.channel, p->type2.data);//输出数据无效
                    }
                }
    #if CONFIG_IDF_TARGET_ESP32S2
                else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_2) 
                {
                    ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %x", 2, p->type1.channel, p->type1.data);
                } else if (ADC_CONV_MODE == ADC_CONV_SINGLE_UNIT_1) 
                {
                    ESP_LOGI(TAG, "Unit: %d, Channel: %d, Value: %d", 1, p->type1.channel, p->type1.data);
                }
    #endif  //#if CONFIG_IDF_TARGET_ESP32S2
    #endif
            }
            //See `note 1`
            vTaskDelay(1);//程序运行太快，防止任务看门狗超时
        } else if (ret == ESP_ERR_TIMEOUT) {
            /**
             * ``ESP_ERR_TIMEOUT``: If ADC conversion is not finished until Timeout, you'll get this return error.
             * Here we set Timeout ``portMAX_DELAY``, so you'll never reach this branch.
             */
            ESP_LOGW(TAG, "No data, increase timeout or reduce conv_num_each_intr");
            vTaskDelay(1000);
        }
    }  
    adc_digi_stop();
    ret = adc_digi_deinitialize();
    assert(ret == ESP_OK);
}

